/*
4K 内存页, 文件读写1次, 统计TLB
2M 内存大页, 文件读写1次, 统计TLB
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>

int gen_3M_file(char* file)
{
    struct stat file_stat;
    int ret;
    ret = stat(file, &file_stat);
    if (ret)
    {
        char buf[1024] = { 0 };
        int fd = open(file, O_WRONLY | O_CREAT);
        if (fd < 0)
        {
            perror("创建 文件失败");
            exit(1);
        }
        for (int i = 0; i < 1024 * 3;i++) {
            write(fd, buf, sizeof(buf));
        }
        close(fd);
        ret = 0;
    }
    return ret;
}
int main(int argc, char* argv[])
{
    char file[16] = "/tmp/3M.img";
    uint32_t file_size = 1024 * 1024 * 3;   // 3M
    void* ptr = NULL;
    gen_3M_file(file);

    int fd = open(file, O_RDWR);
    if (fd < 0) {
        perror("打开文件失败:");
        exit(0);
    }

    if (argc == 1)
    {
        printf("使用 HugePages大内存页 读写\n");
        ptr = mmap(NULL, file_size, PROT_READ | PROT_WRITE,
            MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, fd, 0);
        if (ptr == MAP_FAILED) {
            perror("mmap");
            exit(1);
        }
    }
    else {
        printf("使用 普通4k 内存页 读写\n");
        ptr = mmap(NULL, file_size, PROT_READ | PROT_WRITE,
            MAP_PRIVATE | MAP_SHARED, fd, 0);
        if (ptr == MAP_FAILED) {
            perror("mmap");
            exit(1);
        }
    }
    char buf[1024] = { 0 };
    int len = 1;
    int count = 0;
    // 读一次
    while (len > 0) {
        len = read(fd, buf, sizeof(buf));
        count++;
        // printf("count=%d\n",count);
    }
    // 写一次
    for (int i = 0; i < 1024 * 3;i++) {
        write(fd, buf, sizeof(buf));
    }

    // 释放资源
    munmap(ptr, file_size);
    close(fd);

    // 1.先执行 ps -o majflt,minflt -p pid 读取页中断TLB次数
    // 2.在输入任意字符
    getchar();

    return 0;
}

/* 测试1: HugePages 大页内存页

./12_HugePage内存大页_TLB页中断统计.out
使用 HugePages大内存页 读写

ps -o majflt,minflt -p pid
MAJFLT MINFLT
     0     76
 */



 /* 测试2: 4K 内存页对齐

 ./12_HugePage内存大页_TLB页中断统计.out test
 ps -o majflt,minflt -p 248838
 MAJFLT MINFLT
      0    176

 cat /proc/248838/stat
 248838 (12_HugePage内�) S 248833 248838 248838 0 -1 0 176 ...
  */